package com.example.zmade.service;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import com.example.zmade.IMyAidlInterface;
import com.example.zmade.MainActivity;
import com.example.zmade.SendData;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import android_serialport_api.ComPort;

import static com.example.zmade.Func.getX1X2;
import static com.example.zmade.Func.getX1X2II;
import static com.example.zmade.Func.toUnShort;
import static com.example.zmade.Func.toUnsigned;
import static com.example.zmade.SendData.CommSendCmd;

public class BackService extends Service {
    final ComPort com = new ComPort();
    private float temperature,humidity,targetTemperature;
    private boolean lockstate;//开门：true  关门：false
    private Lock locker = new ReentrantLock();
    private Condition waiter = locker.newCondition();
    private final int timeout = 200;
    public BackService() {
    }
    public void initSerialport(){
        boolean bOpen = com.open("/dev/ttyS4", 9600, new ComPort.DataHandler() {
            @Override
            public void onDataReceived(String comName, byte[] buffer, int size) {
                if (mHandler != null) {
                    if (SendData.check_recvData(buffer, size)) {
                        Message msg = Message.obtain();
                        msg.obj = buffer;
                        msg.arg1 = size;
                        switch (buffer[2]) {
                            case (byte) 0x81:
                                msg.what = 1;
                                break;
                            case (byte) 0x82:
                                msg.what = 2;
                                break;
                        }
                        mHandler.sendMessage(msg);
                    }
                }
            }
        });
        if (bOpen) {
            Log.i("串口打开", "成功");
        } else {
            Log.e("串口打开", "失败");
        }
    }
    public Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            byte[] data = (byte[]) msg.obj;
            int len = msg.arg1;
            switch (msg.what) {
                case 1:getTemperature_resp(data,len);
                getHumidity_resp(data,len);
                isCabinetUnlock_resp(data,len);
                    break;
                case 2:getTargetTemperatre_resp(data,len);
                    break;
            }
        }
    };

    public float getTemperature_resp(byte[] _data,int _len){
        temperature=(float)(short)(toUnShort(_data[7])<<8|toUnShort(_data[6]))/10;
        return temperature;
    }
    public float getHumidity_resp(byte[] _data,int _len){
        humidity=(float)(short)(toUnShort(_data[5])<<8|toUnShort(_data[4]))/10;
        return humidity;
    }
    public boolean isCabinetUnlock_resp(byte[] _data,int _len){
        if(_data[10]==0x00){
            lockstate=false;
        }
        else{
            lockstate=true;
        }
        return lockstate;
    }
    public float getTargetTemperatre_resp(byte[] _data,int _len){
        targetTemperature=(float)(((short)_data[5]<<8)|_data[4])/10;
        return targetTemperature;
    }

    IMyAidlInterface.Stub mBind=new IMyAidlInterface.Stub(){
        @Override
        public float getTemperature() throws RemoteException {
            return temperature;
        }

        @Override
        public float getHumidity() throws RemoteException {
            return humidity;
        }

        @Override
        public boolean isCabinetUnlock() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x01,1,new byte[]{(byte)0X00});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return lockstate;
        }

        @Override
        public float getTargetTemperature() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x02,1,new byte[]{(byte)0X00});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return targetTemperature;
        }

        @Override
        public boolean lockCabinet() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x11,1,new byte[]{(byte)0X00});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return true;
        }

        @Override
        public boolean unlockCabinet() throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x11,1,new byte[]{(byte)0X01});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return true;
        }

        @Override
        public boolean setTargetTemperature(float t) throws RemoteException {
            locker.lock();
            byte[] data=CommSendCmd((byte) 0x13,10,new byte[]{getX1X2II(t)[0],getX1X2II(t)[1],0x19,0x00,0x00,0x00,0x50,0x00,0x14,0x00});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return true;
        }

        @Override
        public boolean getSystemTime() throws RemoteException {
            locker.lock();
            Calendar calendar = Calendar.getInstance();
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH)+1;
            int day = calendar.get(Calendar.DAY_OF_MONTH);
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            int minute = calendar.get(Calendar.MINUTE);
            byte byt_year= (byte) (year%100);
            byte[] data=CommSendCmd((byte) 0x14,5,new byte[]{byt_year,(byte)month,(byte)day,(byte)hour,(byte) minute});
            com.sendData(data,data.length);
            try {
                waiter.await(timeout, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            locker.unlock();
            return true;
        }

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        initSerialport();
        return mBind;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
}
